using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Text;
using GMID = System.Int64;

namespace Cobalt75.GreyMatter
{
    public class GMRelationCollection<T> : IEnumerable<T>
       where T : GMTable
    {
        GMTable pParentObject;
        public GMRelationCollection(GMTable parentObject)
        {
            pParentObject = parentObject;
            Cobalt75.GreyMatter.GMCommunicator com = pParentObject.Communicator;
            pQuery = com.RelationLookupQuery(parentObject.GetType(), typeof(T), null);
        }
        GMQuery pQuery;
        GMRelationCaching pCaching = GMRelationCaching.Updating;
        public GMQuery Query
        {
            get
            {
                return pQuery;
            }
        }
        public GMRelationCaching Caching
        {
            get
            {
                return pCaching;
            }
            set
            {
                pCaching = value;
                GetList();
            }
        }
        T[] pCache;
        GMID[] pIDCache;
        Int64 pListTicks;
        bool pGotList = false;
        void GetList()
        {
            pQuery.SetParameter("parentID", pParentObject.Id);
            if (pCaching == GMRelationCaching.Snapshot)
            {
                pCache = pParentObject.Communicator.Select<T>(pQuery);
                pIDCache = new GMID[pCache.Length];
                for (int i = pCache.Length; i-- > 0; )
                {
                    pIDCache[i] = pCache[i].Id;
                }
            }
            else
            {
                pIDCache = pParentObject.Communicator.SelectIDs(pQuery);
                pCache = new T[pIDCache.Length];
                pListTicks = pParentObject.Communicator.GetTableSync(pQuery.pTables.ToArray());
            }
            pGotList = true;
        }
        public bool ListIsOutdated
        {
            get
            {
                Int64 newTicks = pParentObject.Communicator.GetTableSync(pQuery.pTables.ToArray());
                if (newTicks > pListTicks)
                {
                    return (true);
                }
                return (false);
            }
        }
        public T this[int index]
        {
            get
            {
                if (!pGotList)
                {
                    GetList();
                }
                else if (ListIsOutdated && pCaching == GMRelationCaching.Updating)
                {
                    GetList();
                }
                if (pCache[index] == null)
                {
                    pCache[index] = pParentObject.Communicator.SelectFromId<T>(pIDCache[index], true);
                }
                return (pCache[index]);

            }
        }
        public void CreateLink(T newObj)
        {
            pParentObject.Communicator.CreateLink(pParentObject, newObj, null);
        }
        public void DeleteLink(T newObj)
        {
            pParentObject.Communicator.DeleteLink(pParentObject, newObj, null);
        }
        public IEnumerator<T> GetEnumerator()
        {
            if (!pGotList)
            {
                GetList();
            }
            else if (ListIsOutdated && pCaching == GMRelationCaching.Updating)
            {
                GetList();
            }
            for (int i = 0; i < pIDCache.Length; i++)
            {
                yield return this[i];
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

    }


}
